package com.netty.pubsub;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.netty.domain.IMessage;
import com.netty.handler.WebSocketNettyHandler;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.Objects;

/**
 * @author sixiaojie
 * @date 2020-08-24-13:47
 */
@Component
public class MessageReceive {

    /**
     * 订阅消息 , 发送给指定用户
     *
     * @param object
     */
    public void getMessageToOne(String object) {
        Jackson2JsonRedisSerializer serializer = getSerializer(IMessage.class);
        String pushMessageBody = (String) serializer.deserialize(object.getBytes());
        System.out.println("订阅消息,发送给指定用户：" + pushMessageBody);

        // 推送给指定用户的消息
        IMessage iMessage = JSON.parseObject(object, IMessage.class);
        String userId = iMessage.getReceive();

        Map<String, ChannelHandlerContext> contextMap = WebSocketNettyHandler.getMAP();
        ChannelHandlerContext handlerContext = contextMap.get(userId);
        Channel channel = handlerContext.channel();
        if (!Objects.isNull(channel)) {
            // 如果该用户的客户端是与本服务器建立的channel , 直接推送消息
            channel.writeAndFlush(new TextWebSocketFrame(pushMessageBody));
        }

    }

    /**
     * 订阅消息 , 发送给所有用户
     *
     * @param object
     */
    public void getMessageToAll(String object) throws JsonProcessingException {
        Jackson2JsonRedisSerializer serializer = getSerializer(String.class);
        String pushMessageBody = (String) serializer.deserialize(object.getBytes());
        System.out.println("订阅消息，发送给所有用户：" + pushMessageBody);

        IMessage iMessage = JSON.parseObject(pushMessageBody, IMessage.class);
        Map<String, ChannelHandlerContext> contextMap = WebSocketNettyHandler.getMAP();
        ChannelHandlerContext context = contextMap.get(iMessage.getSend());
        for (ChannelHandlerContext ctx : contextMap.values()) {
            // 排除自身
            if (ctx == context) {
                continue;
            }
            ctx.channel().writeAndFlush(new TextWebSocketFrame(pushMessageBody));
        }

    }

    /**
     * 序列化和反序列化
     * @param clazz
     * @return
     */
    private Jackson2JsonRedisSerializer getSerializer(Class clazz) {
        // 序列化对象（特别注意：发布的时候需要设置序列化；订阅方也需要设置序列化）
        Jackson2JsonRedisSerializer seria = new Jackson2JsonRedisSerializer(clazz);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        seria.setObjectMapper(objectMapper);
        return seria;

    }

}
